package org.sky.framework.mybatis;

import java.util.Collection;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;

public class BaseMapper {

	SqlSessionTemplate sqlSessionTemplate;

	public BaseMapper(SqlSessionTemplate sqlSessionTemplate) {
		this.sqlSessionTemplate = sqlSessionTemplate;
	}

	/**
	 * 批量执行
	 * 
	 * @param clazz   执行类
	 * @param method  方法名
	 * @param entites 数据
	 * @throws Exception
	 */
	public void batchExecute(Class<?> clazz, String method, Collection<?> entites) throws Exception {
		// 新获取一个模式为BATCH，自动提交为false的session
		// 如果自动提交设置为true,将无法控制提交的条数，改为最后统一提交，可能导致内存溢出
		SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
		try {
			if (entites != null && !entites.isEmpty()) {
				int size = entites.size();
				int i = 0;
				// 执行类型: 1-insert, 2-update, 3-delete...
				int type = executeType(method);
				StringBuilder statement = new StringBuilder();
				statement.append(clazz.getName()).append('.').append(method);
				// 遍历
				for (Object entity : entites) {
					// session.update("com.xx.mapper.Mapper.updateByPrimaryKeySelective",entity);
					switch (type) {
					case 1:
						session.insert(statement.toString(), entity);
						break;
					case 2:
						session.update(statement.toString(), entity);
						break;
					case 3:
						session.delete(statement.toString(), entity);
						break;
					default:
						break;
					}
					//
					if ((i > 0 && i % 1000 == 0) || i == size - 1) {
						// 手动每1000个一提交，提交后无法回滚
						session.commit();
						// 清理缓存，防止溢出
						session.clearCache();
					}
					++i;
				}
			}
		} catch (Exception e) {
			// 没有提交的数据可以回滚
			session.rollback();
			throw e;
		} finally {
			session.close();
		}
	}

	/**
	 * 执行类型: 1-insert, 2-update, 3-delete...
	 * 
	 * @param method
	 * @return
	 */
	private int executeType(String method) {
		if (method.contains("insert")) {
			return 1;
		}
		if (method.contains("update")) {
			return 2;
		}
		if (method.contains("delete")) {
			return 3;
		}
		return 0;
	}

}
